package com.company.eos.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateRange;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.company.eos.controller.form.meeting.*;
import com.company.eos.domain.AuditFlow;
import com.company.eos.domain.AuditMeeting;
import com.company.eos.mapper.AuditFlowMapper;
import com.company.eos.service.AuditDetailService;
import com.company.eos.service.AuditFlowService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import com.company.eos.common.util.PageUtils;
import com.company.eos.common.R;
import com.company.eos.config.tencent.TrtcUtil;
import com.company.eos.service.AuditMeetingService;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

/**
 * @author: Song, Wei
 * @date: 2022-03-03
 */
@Slf4j
@RestController
@RequestMapping("/meeting")
@Tag(name = "会议模块Web接口")
public class AuditMeetingController {

    @Autowired
    private AuditMeetingService auditMeetingService;
    @Autowired
    private TrtcUtil trtcUtil;
    @Autowired
    private AuditFlowService auditFlowService;
    @Resource
    private AuditFlowMapper auditFlowMapper;
    @Autowired
    private AuditDetailService auditDetailService;

    @Value("${trtc.appid}")
    private int appId;

    @PostMapping("/searchOfflineMeetingByPage")
    @Operation(summary = "查询线下会议分页表单")
    @SaCheckLogin
    public R searchOfflineMeetingByPage(@Valid @RequestBody SearchOfflineMeetingByPageForm form) {
        log.info("查询线下会议分页表单，参数：{}", form);
        @NotNull(message = "page不能为空") @Min(value = 1, message = "page不能小于1") Integer page = form.getPage();
        @NotNull(message = "length不能为空") @Range(min = 10, max = 50, message = "length必须在10～50之间") Integer length = form.getLength();
        int start = (page - 1) * length;
        HashMap<Object, Object> param = new HashMap<Object, Object>() {{
            put("date", form.getDate());
            put("mold", form.getMold());
            put("userId", StpUtil.getLoginIdAsInt());
            put("start", start);
            put("length", length);
        }};
        // 更新会议的状态
        auditMeetingService.updateOfflineMeetingStatus();
        PageUtils pageUtils = auditMeetingService.searchOfflineMeetingByPage(param);

        return R.ok().put("page", pageUtils);
    }

    @PostMapping("/searchOnlineMeetingByPage")
    @Operation(summary = "查询线上会议分页")
    @SaCheckLogin
    public R searchOnlineMeetingByPage(@Valid @RequestBody SearchOfflineMeetingByPageForm form) {
        log.info("查询线上会议分页，参数：{}", form);
        @NotNull(message = "page不能为空") @Min(value = 1, message = "page不能小于1") int page = form.getPage();
        @NotNull(message = "length不能为空") @Range(min = 10, max = 50, message = "length必须在10～50之间") int length = form.getLength();
        int start = (page - 1) * length;
        HashMap<Object, Object> param = new HashMap<Object, Object>() {{
            put("date", form.getDate());
            put("mold", form.getMold());
            put("userId", StpUtil.getLoginId());
            put("start", start);
            put("length", length);
        }};
        // 更新会议的状态
        auditMeetingService.updateOnlineMeetingStatus();
        PageUtils pageUtils = auditMeetingService.searchOnlineMeetingByPage(param);
        return R.ok().put("page", pageUtils);
    }

    @PostMapping("/insert")
    @Operation(summary = "添加会议")
    @SaCheckLogin
    public R insert(@Valid @RequestBody InsertMeetingForm form) {
        log.info("添加会议，参数：{}", form);
        DateTime start = DateUtil.parse(form.getDate() + " " + form.getStart());
        DateTime end = DateUtil.parse(form.getDate() + " " + form.getEnd());
        if (start.isAfterOrEquals(end)) {
            return R.error("结束时间必须大于开始时间");
        } else if (new DateTime().isAfterOrEquals(start)) {
            return R.error("会议开始时间不能早于当前时间");
        }
        AuditMeeting auditMeeting = JSONUtil.parse(form).toBean(AuditMeeting.class);
        auditMeeting.setUuid(UUID.randomUUID().toString(true));
        auditMeeting.setCreatorId(StpUtil.getLoginIdAsInt());
        auditMeeting.setStatus(1);
        auditMeeting.setCreateTime(new Date());
        // 会议申请，需要插入对应的审批流表和审批详情表
        int flowId = auditFlowService.insertMeetingAudit(auditMeeting);
        AuditFlow flow = auditFlowMapper.selectById(flowId);
        // 审核详情表
        auditDetailService.insertAuditMeeting(auditMeeting, flow);
        auditMeeting.setFlowId(flowId);
        int row = auditMeetingService.insert(auditMeeting);
        return R.ok().put("row", row);
    }

    @PostMapping("/searchOfflineMeetingInWeek")
    @Operation(summary = "查询某个会议室的一周会议")
    @SaCheckLogin
    public R searchOfflineMeetingInWeek(@Valid @RequestBody SearchOfflineMeetingInWeekForm form) {
        log.info("查询某个会议室的一周会议，参数：{}", form);
        @Pattern(regexp = "^((((1[6-9]|[2-9]\\d)\\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-0?2-(0?[1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-0?2-29-))$", message = "date内容不正确") String date = form.getDate();
        DateTime startDate, endDate;
        if (date != null && date.length() > 0) {
            // 从date开始，生成七天日期
            startDate = DateUtil.parseDate(date);
            endDate = startDate.offsetNew(DateField.DAY_OF_WEEK, 6);
        } else {
            // 查询当前日期， 生成本周日期
            startDate = DateUtil.beginOfWeek(new Date());
            endDate = DateUtil.endOfWeek(new Date());
        }

        // 更新会议的状态
        auditMeetingService.updateOfflineMeetingStatus();

        // 封装查询条件
        HashMap<Object, Object> param = new HashMap<Object, Object>() {{
            put("place", form.getName());
            put("startDate", startDate.toDateStr());
            put("endDate", endDate.toDateStr());
            put("mold", form.getMold());
            put("userId", StpUtil.getLoginIdAsInt());
        }};

        // 获取查询结果
        ArrayList<HashMap> list = auditMeetingService.searchOfflineMeetingInWeek(param);

        // 生成周日历的文字标题
        ArrayList<Object> days = new ArrayList<>();
        DateRange range = DateUtil.range(startDate, endDate, DateField.DAY_OF_WEEK);
        range.forEach(item -> {
            JSONObject json = new JSONObject();
            json.set("date", item.toString("MM/dd"));
            json.set("day", item.dayOfWeekEnum().toChinese("周"));
            days.add(json);
        });

        return R.ok().put("list", list).put("days", days);

    }

    @PostMapping("/searchMeetingInfo")
    @Operation(summary = "'查询会议信息'")
    @SaCheckLogin
    public R searchMeetingInfo(@Valid @RequestBody SearchMeetingInfoForm form) {
        log.info("查询会议信息，参数：{}", form);
        // 更新线下会议的状态
        auditMeetingService.updateOfflineMeetingStatus();
        // 更新线上会议的状态
        auditMeetingService.updateOnlineMeetingStatus();
        HashMap map = auditMeetingService.searchMeetingInfo(form.getStatus(), form.getId());
        return R.ok(map);
    }

    @DeleteMapping("/deleteMeetingApplication")
    @Operation(summary = "删除会议申请")
    @SaCheckLogin
    public R deleteMeetingApplication(@Valid @RequestBody DeleteMeetingApplicationForm form) {
        log.info("删除会议申请，参数：{}", form);
        HashMap param = JSONUtil.parseObj(form).toBean(HashMap.class);
        param.put("creatorId", StpUtil.getLoginIdAsLong());
        param.put("userId", StpUtil.getLoginIdAsLong());
        int rows = auditMeetingService.deleteMeetingApplication(param);
        return R.ok().put("rows", rows);
    }

    @GetMapping("/searchMyUserSig")
    @Operation(summary = "获取用户签名")
    @SaCheckLogin
    public R searchMyUserSig() {
        log.info("获取用户签名");
        final int userId = StpUtil.getLoginIdAsInt();
        // 获取用户签名
        final String userSig = trtcUtil.genUserSig(userId + "");
        return R.ok().put("userSig", userSig).put("userId", userId).put("appId", appId);
    }

    @PostMapping("/searchRoomIdByUuid")
    @Operation(summary = "查询视频会议RoomId")
    @SaCheckLogin
    public R searchRoomIdByUuid(@Valid @RequestBody SearchRoomIdByUUIDForm form) {
        log.info("查询视频会议RoomId，参数：{}", form);
        final Long roomId = auditMeetingService.searchRoomIdByUuid(form.getUuid());
        return R.ok().put("roomId", roomId);
    }

    @PostMapping("/searchOnlineMeetingMembers")
    @Operation(summary = "查询线上会议成员")
    @SaCheckLogin
    public R searchOnlineMeetingMembers(@Valid @RequestBody SearchOnlineMeetingMembersForm form) {
        log.info("查询线上会议成员，参数：{}", form);
        final HashMap param = JSONUtil.parse(form).toBean(HashMap.class);
        param.put("userId", StpUtil.getLoginIdAsInt());
        final ArrayList<HashMap> list = auditMeetingService.searchOnlineMeetingMembers(param);
        return R.ok().put("list", list);
    }

    @PostMapping("/updateMeetingPresent")
    @Operation(summary = "执行会议签到")
    @SaCheckLogin
    public R updateMeetingPresent(@Valid @RequestBody UpdateMeetingPresentForm form) {
        log.info("执行会议签到，参数：{}", form);
        final HashMap<Object, Object> param = new HashMap<Object, Object>() {{
            put("meetingId", form.getMeetingId());
            put("userId", StpUtil.getLoginIdAsInt());
        }};

        // 查询是否可以签到
        final boolean bool = auditMeetingService.searchCanCheckMeeting(param);

        if (bool) {
            final int rows = auditMeetingService.updateMeetingPresent(param);
            return R.ok().put("rows", rows);
        } else {
            return R.ok().put("rows", 0);
        }
    }

}
